﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Diagnostics;

namespace Ict.DataAccess.Linq
{
    public class Deletable<T> : Modifiable, IQueryable<T>
    {
        /// <summary>
        /// 删除满足查询条件的记录
        /// 条件以查询形式表示
        /// </summary>
        /// <param name="condition">查询条件</param>
        /// <returns>被删除的记录数</returns>
        public int Delete(IQueryable<T> condition)
        {
            if (!(condition is Selectable<T>))
                throw new ArgumentException("Type of condition must be Selectable<TElement>.");
            this.query = (Selectable<T>)condition;

            return Delete<T>();
        }

        /// <summary>
        /// 删除满足查询条件的记录
        /// 条件以Lambda表达式表示
        /// </summary>
        /// <param name="condition"></param>
        /// <returns></returns>
        public int Delete(Expression<Func<T, bool>> condition)
        {
            this.WhereClause.Add(condition.Body);

            return Delete<T>();
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <typeparam name="TElement"></typeparam>
        /// <returns></returns>
        public int Delete<TElement>()
        {
            StringBuilder stringBuilder = new StringBuilder();
            DmlEncoder encoder = DataContext.Current.CreateSqlEncoder();

            stringBuilder.Append("DELETE ");
            
            if (query != null)
            {
                stringBuilder.Append(MapTableAlias<TElement>());
                stringBuilder.Append(" FROM ");
                query.BuildQueryList(stringBuilder);
            }
            else
            {
                stringBuilder.Append(" FROM ");
                stringBuilder.Append(TableMapper<TElement>.TableName);
            }
            if (query != null)
            {
                StringBuilder conditionBuilder = new StringBuilder();
                query.BuildCondition(conditionBuilder);
                if (conditionBuilder.Length > 0)
                {
                    stringBuilder.Append(" WHERE ");
                    stringBuilder.Append(conditionBuilder.ToString());
                }
            }
            else if (whereClause != null)
            {
                stringBuilder.Append(" WHERE ");
                BuildCondition<T>(stringBuilder, whereClause);
            }
            string sql = stringBuilder.ToString();
            Debug.WriteLine(sql);

            int n = 0;
            using (Executor exec = (Provider as ModifiableProvider).Executor)
            {
                n = exec.Delete<TElement>(sql);
            }
            return n;
        }

        internal override void AddExpression(string methodName, System.Linq.Expressions.Expression expression)
        {
            if (methodName == "Where")
            {
                if (query != null)
                    query.WhereClause.Add(((expression as UnaryExpression).Operand as LambdaExpression).Body);
                else
                    WhereClause.Add(((expression as UnaryExpression).Operand as LambdaExpression).Body);
            }
            else
                throw new NotSupportedException(string.Format("不支持的方法调用：{0}", methodName));
        }

        internal override Modifiable Clone<TElement>()
        {
            Deletable<TElement> modifier = new Deletable<TElement>();
            modifier.Provider = this.Provider;

            return modifier;
        }

        internal override Modifiable Clone()
        {
            return Clone<T>();
        }

        public override Type ElementType
        {
            get { return typeof(T); }
        }

        #region IEnumerable<T> 成员

        public new IEnumerator<T> GetEnumerator()
        {
            return (IEnumerator<T>)GetEnumerator();
        }

        #endregion
    }
}
